package com.ddxcloud.movie.service.impl;

import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import com.ddxcloud.common.utils.SignUtil;
import com.ddxcloud.movie.config.movie.MovieConfig;
import com.ddxcloud.movie.dto.*;
import com.ddxcloud.movie.entity.Channel;
import com.ddxcloud.movie.service.ChannelService;
import com.ddxcloud.movie.service.MoviesService;
import com.ddxcloud.movie.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
@Slf4j
public class MoviesServiceImpl implements MoviesService {

    @Resource
    ChannelService channelService;

    @Override
    public JSONObject getAllCity() {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/common/getAllCity";
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .timeout(20000)
                .execute().body();
        return JSONObject.parseObject(result);
    }

    @Override
    public Object getCity(String location) {
        // 调用高德根据经纬度获取城市
        String url = "https://restapi.amap.com/v3/geocode/regeo?location=" + location + "&key=01dc142f59c9b174bab47d0cb0bbf9ae&output=json";
        String result = HttpRequest.get(url).execute().body();
        JSONObject body = JSONObject.parseObject(result);
        JSONObject regeocode = null;
        if (body != null) {
            regeocode = body.getJSONObject("regeocode");
        }
        JSONObject addressComponent = null;
        if (regeocode != null) {
            addressComponent = regeocode.getJSONObject("addressComponent");
        }
        Object city = null;
        if (addressComponent != null) {
            city = addressComponent.get("city");
        }
        if (city == null || city.equals("")) {
            if (addressComponent != null) {
                city = addressComponent.get("province");
            }
        }
        return city;
    }

    @Override
    public IPage<Object> getMovies(PageDTO dto) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getMovies";
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        List data = jsonObject.getJSONArray("data");
        List list = new ArrayList<>();
        return getResult(data, list, dto.getPageNum(), dto.getPageSize());
    }

    @Override
    public IPage<Object> getFutureMovies(PageDTO dto) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getFutureMovies";
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        List data = jsonObject.getJSONArray("data");
        List list = new ArrayList<>();
        return getResult(data, list, dto.getPageNum(), dto.getPageSize());
    }

    @Override
    public JSONObject getMovieInfo(String filmId) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getMovieInfo?filmId=" + filmId;
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        return jsonObject;
    }

    @Override
    public List getCinemas(CinemasDTO dto) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getCinemas?cityId=" + dto.getCityId();
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        return JSONUtil.toList(jsonObject.getString("data"), CinemasVO.class);
    }

    @Override
    public JSONObject getCinemaInfo(String cityId, String cinemaId) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getCinemaInfo";
        Map<String, Object> params = new HashMap<>();
        params.put("cityId", cityId);
        params.put("cinemaId", cinemaId);
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .form(params)
                .timeout(20000)
                .execute().body();
        return JSONObject.parseObject(result).getJSONObject("data");
    }

    @Override
    public List<ShowsVO> getShows(ShowsDTO dto) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getShows";
        Map<String, Object> params = new HashMap<>();
        params.put("cinemaId", dto.getCinemaId());
        params.put("searchFilmId", dto.getSearchFilmId());
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .form(params)
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        List<ShowsVO> list = JSONUtil.toList(jsonObject.getString("data"), ShowsVO.class);
        for (ShowsVO showsVO : list) {
            for (DatesVO datesVO : showsVO.getDates()) {
                for (ShowsDatesListVO listVO : datesVO.getList()) {
                    // 特惠出票结算价
                    listVO.setSettlementPrice(listVO.getSettlementPrice().add(channel.getChannelAmount()));
                }
            }
        }
        return list;
    }

    @Override
    public SeatsVO getSeats(String showId, String cinemaId) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/movie/v1/getSeats";
        Map<String, Object> params = new HashMap<>();
        params.put("showId", showId);
        params.put("cinemaId", cinemaId);
        String result = HttpRequest.get(url)
                .header("appId", channel.getChannelId())
                .form(params)
                .timeout(20000)
                .execute().body();
        JSONObject jsonObject = JSONObject.parseObject(result);
        jsonObject = jsonObject.getJSONObject("data");

        SeatsVO vo = new SeatsVO();
        vo.setColumns(jsonObject.getIntValue("columns"));
        vo.setRows(jsonObject.getIntValue("rows"));
        Map<String, Object> seats = jsonObject.getJSONObject("seats");
        Map<String, Object> seatsResult = new HashMap<>();
        for (Map.Entry<String, Object> entry : seats.entrySet()) {
            SeatsInfoVO info = JSONUtil.toBean(JSONUtil.toJsonStr(entry.getValue()), SeatsInfoVO.class);
            try {
                // 特惠出票结算价
                info.setSettlementPrice(info.getSettlementPrice().add(channel.getChannelAmount()));
                // 快捷出票结算价
                info.setSettlementQuickPrice(info.getSettlementQuickPrice().add(channel.getChannelAmount()));
            } catch (Exception e) {
                log.error("seatId: {} errMsg: {}", info.getSeatId(), e.getMessage());
                info.setStatus(2); // 缺少结算金额的情况下标记该座位为不可售
            }
            seatsResult.put(entry.getKey(), info);
        }
        vo.setSeats(seatsResult);
        return vo;
    }

    @Override
    public JSONObject createOrder(AddOrderDTO dto) {
        Channel channel = channelService.getChannel();
        String url = MovieConfig.url + "/open/order/v1/addOrder";
        Map map = JSONUtil.toBean(JSONUtil.toJsonStr(dto), Map.class);
        map.put("sign", SignUtil.getSign(map, channel.getChannelSecret()));
        String result = HttpRequest.post(url)
                .header("appId", channel.getChannelId())
                .body(JSONUtil.toJsonStr(map))
                .timeout(20000)
                .execute().body();
        log.info("createOrder response params: {}", result);
        JSONObject jsonObject = JSONObject.parseObject(result);
        if (jsonObject.containsKey("data")) {
            AddOrderVO vo = JSONUtil.toBean(jsonObject.getString("data"), AddOrderVO.class);
            vo.setOrderAmount(vo.getOrderAmount().add(channel.getChannelAmount()));
            jsonObject.put("data", JSONUtil.toJsonStr(vo));
        }
        return jsonObject;
    }

    @Override
    public JSONObject confirmOrder(ConfirmOrderDTO dto, Channel channel) {
        String url = MovieConfig.url + "/open/order/v1/confirmOrder";
        Map map = JSONUtil.toBean(JSONUtil.toJsonStr(dto), Map.class);
        map.put("sign", SignUtil.getSign(map, channel.getChannelSecret()));
        String result = HttpRequest.post(url)
                .header("appId", channel.getChannelId())
                .body(JSONUtil.toJsonStr(map))
                .timeout(20000)
                .execute().body();
        log.info("confirmOrder response params: {}", result);
        return JSONObject.parseObject(result);
    }

    /**
     * 分页方法
     * @param data
     * @param listsort
     * @param pageNum
     * @param pageSize
     * @return
     */
    @NotNull
    private IPage<Object> getResult(List data, List listsort, Integer pageNum, Integer pageSize) {
        for(int i=(pageNum>1?pageSize*(pageNum-1):0);i<(pageNum*pageSize>data.size()?(pageNum*pageSize)-((pageNum*pageSize)-data.size()):pageNum*pageSize);i++){
            listsort.add(data.get(i));
        }
        IPage<Object> page = new Page<>();
        page.setCurrent(pageNum);
        page.setSize(pageSize);
        page.setTotal(data.size());
        page.setRecords(listsort);
        page.setPages((data.size() / pageSize) + (data.size() % pageSize > 0 ? 1 : 0));
        return page;
    }
}
